/* $Id: truncate.jquery.js 33 2009-10-22 20:36:28Z geraldb $

Unobtrusive jQuery Text Truncation.

Overview:
	jQuery.truncate():
		This function takes a string and truncates it down to the specified
		length without chopping words in half.

		Parameters:
			text: (String) Text to be truncated.
				default: ''
			max: (Number) Max length for truncated text.
				default: 100
			stop: (Regex) Regular Expression to determine what a word is not.
				default: /\s/ (whitespace)

		Usage:
			var new_text = jQuery.truncate({text: 'some piece of text', max: 12});
			Output: new_text == 'some piece';

	jQuery.fn.truncate()
		This method takes the contents of an object and attempts to truncate.
		It then adds links to toggle opened and closed states.

		Parameters:
			ignoreParents: (Boolean) If set to true, this will ignore nodes with child
				nodes.
				default: false
			max: (Number) Max length for truncated text.
				default: 100
			stop: (Regex) Regular Expression to determine what a word is not.
				default: /[^0-9a-zA-Z]/
			prepend: (String) Text to be prepended to classes on nodes.
				default: 'truncate'
			expandText: (String) Text to show on "expand" link.
				default: 'Show'
			collapseText:  (String) Text to show on "collapse" link.
				default: 'Hide'
			trailText:  (String) Text to show after collapsed text.
				default: '...'

		Usage:
			HTML:
			<ul id="faq">
				<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit</li>
				<li>sed do eiusmod tempor incididunt ut labore et dolore magna</li>
				<li>Ut enim ad minim veniam, quis nostrud exercitation ullamco</li>
			</ul>

			JAVASCRIPT:
			$('#faq li').truncate(25);

Author:
	Brian Reindel(http://www.reindel.com/truncate/), gburns

TODO:
	Documentation
	Use .is(...) to make sure a node isn't truncated twice?
*/

(function($) {
$.fn.truncate = function(options) {
	if ( typeof(options) == 'number' ) options = { max: options };

	var settings = $.extend({
		ignoreParents: false,
		max: 100,
		stop: /[^0-9a-zA-Z]/,
		prepend: 'truncate',
		expandText: 'Show',
		collapseText: 'Hide',
		trailText: '...'
	}, options || {});

	return this.each(function() {
		var $this = $(this);
		var expanded_text = $this.attr('innerHTML');
		var collapsed_text = $.truncate({text: $this.text(), max: settings.max, stop: settings.stop});

		var $collapse_link;
		var $expand_link;

		var expand = function() {
			$this
				.attr({innerHTML: expanded_text})
				.append($collapse_link)
				.removeClass(settings.prepend + '_collapsed');
		};

		var collapse = function() {
			$this
				.attr({innerHTML: collapsed_text + settings.trailText})
				.append($expand_link)
				.addClass(settings.prepend + '_collapsed');
		};

		if ( settings.collapseText ) {
			$collapse_link = $('<a href="javascript:;">' + settings.collapseText + '</a>')
				.addClass(settings.prepend + '_collapse')
				.bind('click', collapse);
		}

		if ( settings.expandText ) {
			$expand_link = $('<a href="javascript:;">' + settings.expandText + '</a>')
				.addClass(settings.prepend + '_expand')
				.bind('click', expand);
		}

		if ( !settings.ignoreParents || (settings.ignoreParents && $this.children().length == 0) ) collapse();
	});
};

$.truncate = function (options) {
	var settings = $.extend({
		text: '',
		max: 100,
		stop: /[^0-9a-zA-Z]/
	}, options || {});

	var max = parseFloat(settings.max);
	if ( settings.text.length <= max ) return settings.text;
	if ( !max ) return settings.text;

	// make sure whole words are not split
	var c;
	while ( max != 0 ) {
		c = settings.text.charAt(max+1);
		if ( c.match(settings.stop) != null ) {
			return settings.text.substring(0, max+1);
		}
		max--;
	}
	return settings.text.substring(0, settings.max);
};
})(jQuery);